package com.icinfo.cloud.provider.punish.common.publicsecurityentrust.service.impl;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.icinfo.cloud.provider.common.constant.Constant;
import com.icinfo.cloud.provider.common.exception.BusinessException;
import com.icinfo.cloud.provider.punish.common.publicsecurityentrust.mapper.CasePublicSecurityEntrustDocumentNumberSegmentMapper;
import com.icinfo.cloud.provider.punish.common.publicsecurityentrust.model.CasePublicSecurityEntrustDocumentNumberSegment;
import com.icinfo.cloud.provider.punish.common.publicsecurityentrust.service.ICasePublicSecurityEntrustDocumentNumberSegmentService;
import com.icinfo.cloud.provider.punish.common.publicsecurityentrust.vo.SegmentUsedNumberCountVo;
import com.icinfo.cloud.provider.punish.common.publicsecurityentrust.vo.UsageSituationVo;
import com.icinfo.cloud.xzcf.provider.member.userinfo.dto.UserDTO;
import com.icinfo.framework.core.service.support.MyBatisServiceSupport;
import com.icinfo.framework.mybatis.mapper.entity.Example;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author HKxxx
 * @date 2024/2/2 10:13
 */
@Service
@Slf4j
public class CasePublicSecurityEntrustDocumentNumberSegmentServiceImpl extends MyBatisServiceSupport implements ICasePublicSecurityEntrustDocumentNumberSegmentService {
    @Resource
    private CasePublicSecurityEntrustDocumentNumberSegmentMapper casePublicSecurityEntrustDocumentNumberSegmentMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insertBatch(List<CasePublicSecurityEntrustDocumentNumberSegment> segmentList) {
        if (CollUtil.isEmpty(segmentList)) {
            return;
        }
        casePublicSecurityEntrustDocumentNumberSegmentMapper.insertBatch(segmentList);
    }

    @Override
    public int updateBySegmentSelective(CasePublicSecurityEntrustDocumentNumberSegment segment) {
        if (Objects.isNull(segment)) {
            throw new BusinessException("公安委托街道文号信息不能为空！");
        }
        return casePublicSecurityEntrustDocumentNumberSegmentMapper.updateByPrimaryKeySelective(segment);
    }

    @Override
    public int updateBySegment(CasePublicSecurityEntrustDocumentNumberSegment segment) {
        if (Objects.isNull(segment)) {
            throw new BusinessException("公安委托街道文号信息不能为空！");
        }
        return casePublicSecurityEntrustDocumentNumberSegmentMapper.updateByPrimaryKey(segment);
    }

    @Override
    public void removeByDocumentNumberId(String documentNumberId) {
        UserDTO user = getUser();
        CasePublicSecurityEntrustDocumentNumberSegment segment = new CasePublicSecurityEntrustDocumentNumberSegment();
        segment.setIsDeleted(Constant.STRING_1)
                .setUpdateTime(new Date())
                .setUpdateUserId(String.valueOf(user.getUserId()))
                .setUpdateUser(user.getRealName());
        Example example = new Example(CasePublicSecurityEntrustDocumentNumberSegment.class);
        example.createCriteria().andEqualTo("documentNumberId", documentNumberId)
                .andEqualTo("isDeleted", Constant.STRING_0);
        casePublicSecurityEntrustDocumentNumberSegmentMapper.updateByExampleSelective(segment, example);
    }

    @Override
    public List<CasePublicSecurityEntrustDocumentNumberSegment> listByDocumentNumberId(String documentNumberId) {
        Example example = new Example(CasePublicSecurityEntrustDocumentNumberSegment.class);
        example.createCriteria().andEqualTo("documentNumberId", documentNumberId)
                .andEqualTo("isDeleted", Constant.STRING_0);
        return casePublicSecurityEntrustDocumentNumberSegmentMapper.selectByExample(example);
    }

    @Override
    public Map<String, Long> groupCountDocumentNumberSegment(List<String> mainIds) {
        List<SegmentUsedNumberCountVo> segmentUsedNumberCountVos =
                casePublicSecurityEntrustDocumentNumberSegmentMapper.groupUsedNumberCountSumByDocumentNumberIds(mainIds);
        if (CollUtil.isEmpty(segmentUsedNumberCountVos)) {
            return Collections.emptyMap();
        }
        return segmentUsedNumberCountVos.stream()
                .collect(Collectors.toMap(SegmentUsedNumberCountVo::getId, SegmentUsedNumberCountVo::getUsedNumberCount));
    }

    @Override
    public CasePublicSecurityEntrustDocumentNumberSegment getDocumentNumberSegment(
            String documentNumber, String entrustOrgCode, String orgCode) {
        return casePublicSecurityEntrustDocumentNumberSegmentMapper.
                getDocumentNumberByEntrustOrgCodeAndOrgCodeAndDocumentNumber(documentNumber, entrustOrgCode, orgCode);
    }

    @Override
    public CasePublicSecurityEntrustDocumentNumberSegment getRemainDocumentNumberInfo(String orgCode, String userOrgCode) {
        Example segmentExample = new Example(CasePublicSecurityEntrustDocumentNumberSegment.class);
        segmentExample.setOrderByClause("number_start ASC");
        segmentExample.createCriteria()
                .andEqualTo("isDeleted", Constant.STRING_0)
                .andEqualTo("entrustOrgCode", orgCode)
                .andEqualTo("orgCode", userOrgCode)
                .andCondition("number_segment != used_number_count");
        List<CasePublicSecurityEntrustDocumentNumberSegment> segments = casePublicSecurityEntrustDocumentNumberSegmentMapper.selectByExample(segmentExample);
        if (CollUtil.isEmpty(segments)) {
            return null;
        }
        List<CasePublicSecurityEntrustDocumentNumberSegment> sortByAsc =
                segments.stream().sorted(Comparator.comparingLong(segment -> Long.parseLong(segment.getNumberStart()))).collect(Collectors.toList());
        // 返回第一个元素
        return sortByAsc.stream().findFirst().orElse(null);
    }

    @Override
    public long getUnusedTotal(String orgCode, String userOrgCode, String documentNumberId) {
        Example example = new Example(CasePublicSecurityEntrustDocumentNumberSegment.class);
        example.createCriteria()
                .andEqualTo("isDeleted", Constant.STRING_0)
                // 大段id
                .andEqualTo("documentNumberId", documentNumberId)
                // 委托单位的orgCode
                .andEqualTo("entrustOrgCode", orgCode)
                // 当前登录人的orgCode
                .andEqualTo("orgCode", userOrgCode)
                // 号段结束不等于已使用的号段
                .andCondition("(number_end != current_number or current_number is null)")
                // 号段数不等于已使用号段数
                .andCondition("number_segment != used_number_count");
        List<CasePublicSecurityEntrustDocumentNumberSegment> segments = casePublicSecurityEntrustDocumentNumberSegmentMapper.selectByExample(example);
        long total = 0L;
        for (CasePublicSecurityEntrustDocumentNumberSegment info : segments) {
            UsageSituationVo usageSituationVo = usageSituation(info);
            Long surplus = usageSituationVo.getSurplus();
            total += surplus;
        }
        // 不足需要+1
        return total + 1;
    }


    public UsageSituationVo usageSituation(CasePublicSecurityEntrustDocumentNumberSegment segment) {
        UsageSituationVo vo = new UsageSituationVo();
        //已用数
        long used = 0L;
        //未用数
        long surplus;
        // 通过使用的号码来判断
        if (StrUtil.isNotBlank(segment.getCurrentNumber())) {
            Long startLong = Long.valueOf(segment.getNumberStart());
            Long usedLong = Long.valueOf(segment.getCurrentNumber());
            Long endLong = Long.valueOf(segment.getNumberEnd());
            // 计算
            used = usedLong - startLong + 1;
            surplus = endLong - usedLong;
        } else {
            surplus = segment.getNumberSegment();
        }
        vo.setUsed(used);
        vo.setSurplus(surplus);
        return vo;
    }

}
